/*
 * tss.h
 *
 *  Created on: 2008-9-20
 *      Author: ant
 */

#ifndef TSS_H_
#define TSS_H_

#include "config.h"

#if defined(PLATFORM_WIN32)

#include <windows.h>
#include <map>

BEGIN_NAMESPACE_TOXIC

typedef void (*cleanup_route)(void*);

namespace detail {

	typedef std::map<DWORD, cleanup_route> IndexCleanupMap;

	class tss {
		CLASS_UNCOPYABLE(tss)
	public:
		explicit tss(cleanup_route cleanup = 0)
		:_index(TlsAlloc()) {
			tssMap().insert(std::make_pair(_index, cleanup));
		}

		~tss() {
			TlsFree(_index);
		}

		void* get() const {
			return TlsGetValue(_index);
		}

		void set(void* value) {
			TlsSetValue(_index, value);
		}

	public:
		static void cleanup();

	private:
		static IndexCleanupMap& tssMap();

	private:
		DWORD _index;
	};

} // namespace detail

END_NAMESPACE_TOXIC

#elif defined(PLATFORM_POSIX)

#include <pthread.h>

BEGIN_NAMESPACE_TOXIC

typedef void (*cleanup_route)(void*);

namespace detail {

	class tss {
		CLASS_UNCOPYABLE(tss)
	public:
		explicit tss(cleanup_route cleanup = 0) {
			pthread_key_create(&_key, cleanup);
		}

		~tss() {
			pthread_key_delete(_key);
		}

		void* get() const {
			return pthread_getspecific(_key);
		}

		void set(void* value) {
			pthread_setspecific(_key, value);
		}

	private:
		pthread_key_t _key;
	};

} // namespace detail

END_NAMESPACE_TOXIC

#else
#error "tss unavailable on this platform"
#endif

#endif /* TSS_H_ */
